package com.dsg.config;

/**
 * @program: erp
 * @description: SQL拦截
 * @author: lironglai
 * @create: 2020-07-10 18:54
 */

import com.dsg.common.security.SystemAuthorizingUser;
import com.dsg.common.util.BeanKit;
import com.dsg.common.util.SingletonLoginUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.Date;
import java.util.HashMap;
import java.util.Properties;
import java.util.regex.Pattern;

@Intercepts({
        @Signature(method = "query", type = Executor.class, args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
        @Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class}),
})
@Slf4j
public class SqlIntercept implements Interceptor {

    private Properties properties;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement mappedStatement = (MappedStatement) args[0];
        Object beanObject = args[1];
        Object target = invocation.getTarget();
        Configuration configuration = mappedStatement.getConfiguration();
        StatementHandler handler = configuration.newStatementHandler((Executor) target, mappedStatement, beanObject, RowBounds.DEFAULT, null, null);
        String methodName = invocation.getMethod().getName();
        BoundSql boundSql = handler.getBoundSql();
        String sql = boundSql.getSql();
        if ("update".equals(methodName)) {
            Date now = new Date();
            String userId = "0", entCode = null;
            try {
                SystemAuthorizingUser sysUser = SingletonLoginUtils.getSystemUser();
                userId = sysUser.getUserId();//当前登录人ID
                entCode = sysUser.getOrgCode();//当前登录人企業編號
            } catch (Exception e) {
                log.warn("无法获取用户信息！");
            }
            log.info("userId=[" + userId + "]");
            if (isInsert(sql)) {//新增时
                // 企業編號
                setProperties(beanObject, "entCode", entCode);
                // 创建时间
                setProperties(beanObject, "createTime", now);
                // 创建人ID
                setProperties(beanObject, "creater", userId);
                // 修改人ID
                setProperties(beanObject, "updater", userId);
                // 修改时间
                setProperties(beanObject, "updateTime", now);
            } else {
                if (isUpdate(sql)) {
                    if (beanObject instanceof HashMap) {
                        if (((HashMap) beanObject).containsKey("et")) {
                            beanObject = ((HashMap) beanObject).get("et");
                        }
                    }
                    // 修改人ID
                    setUpdProperties(beanObject, "updater", userId);
                    // 修改时间
                    setUpdProperties(beanObject, "updateTime", now);
                }
            }
        }
        return invocation.proceed();
    }

    Pattern insertPattern = Pattern.compile("\\s*insert", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);

    protected boolean isInsert(String sql) {
        return insertPattern.matcher(sql).find();
    }

    Pattern updatePattern = Pattern.compile("\\s*update", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);

    protected boolean isUpdate(String sql) {
        return updatePattern.matcher(sql).find();
    }

    private void setProperties(Object beanObject, String propertyName, Object propertyValue) {
        // 判断属性是否存在并赋值
        if (BeanKit.propertyExists(beanObject, propertyName)) {
            Object object = BeanKit.getProperty(beanObject, propertyName);
            if (null == object || "".equals(object.toString().trim())) {
                BeanKit.setProperty(beanObject, propertyName, propertyValue);
            }
        }
    }

    private void setUpdProperties(Object beanObject, String propertyName, Object propertyValue) {
        // 判断属性是否存在并赋值
        if (BeanKit.propertyExists(beanObject, propertyName)) {
            BeanKit.setProperty(beanObject, propertyName, propertyValue);
        }
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
}
